//
// Created by MI T on 2024/8/1.
//

#ifndef UVCCAMERA_UVCPREVIEW_H
#define UVCCAMERA_UVCPREVIEW_H

#include "PluginWindowRender.h"
#include "libuvc/libuvc.h"
#include "libuvc/libuvc_internal.h"
#include "ObjectArray.h"
#include "uv.h"
#include "napi_utils.h"
#include "napi/native_api.h"
#include <native_window/external_window.h>
#include <utility> // for std::pair
#include <sys/mman.h>

#define UVC_FORMAT_FRAME_WINDOW WINDOW_FORMAT_RGBA_8888
#define MAX_FRAME 2

struct FrameData {
    uvc_frame_t *frame;
};

class UvcPreview {
private:
    napi_threadsafe_function func; // 接口回调数据
    char *mSurfaceId;
    int mDisplayTransformState;

    uvc_device_handle_t *mDeviceHandle;
    OHNativeWindow *mPreviewWindow;
    volatile bool mIsRunning;

    int requestWidth, requestHeight; // 设置的预览数据
    int frameWidth, frameHeight;     // 实际使用的预览控件的宽高
    size_t frameBytes;               // 预览数据大小，为了校验数据完整性

    int frameMode; // 使用的类型
    int requestMode;
    pthread_t captureThread;      // 捕获预览流，并且绘制到页面的线程
    pthread_mutex_t captureMutex; // 捕获线程的互斥锁
    pthread_cond_t captureCond;   // 等待专用的条件变量

    pthread_mutex_t surfaceMutex; // 预览互斥锁

    ObjectArray<uvc_frame_t *> previewFrames;

    int prepare_preview(uvc_stream_ctrl_t *ctrl); // 准备预览

    int do_preview(uvc_stream_ctrl_t *ctrl); // 开始预览

    static void uvc_stream_callback(uvc_frame_t *frame, void *vptr_args); // 预览数据回调

    void clearCaptureFrame(); // 清空所有捕获的数据

    void putFrame(uvc_frame_t *frame); // 发送数据

    uvc_frame_t *waitPreviewFrame(); // 等待获取数据


    void drawFrame(uvc_frame_t *frame); // 将数据绘制到控件上去，

    PluginWindowRender *loadRender(); // 获取window窗口的缓存类

    static void *capture_thread_func(void *vptr_args); // 当前捕获线程的回调

    static void preview_thread_call(napi_env env, napi_value jsCb, void *context, void *data);
    // 获取当前使用的分辨率类型
    uvc_frame_format getPreviewFormat();
    size_t getPreviewBytesSize();


public:
    UvcPreview(uvc_device_handle_t *deviceHandler);

    ~UvcPreview();

    bool isRunning() { return mIsRunning; };

    int startPreview();

    int stopPreview();

    int setPreviewSize(int width, int height, int format);

    int setDisplaySurface(char *surfaceId); // 设置预览控件

    // 设置监听回调
    void setPreviewDataListener(napi_env env, napi_value value, int mode);

    // 设置预览图像变换
    bool setDisplayTransformState(int transformState);

    int getDisplayTransformState();
    int getPreviewWidth();
    int getPreviewHeight();
    int loadCurrentFormat();
};


#endif // UVCCAMERA_UVCPREVIEW_H
